//
//  SDKManager.swift
//  
//
//  Created by 孙长坦 on 2022/9/28.
//

import Foundation
import UIKit
import LibBase

public protocol SDKManagerDelegate: AnyObject {
    func share(sdkManager: SDKManager, shareObject: [String: Any], completion: ShareProtocol.Completion?)
    
    func shareParams(completion: @escaping (_ shareParams : [String: String]?) -> Void)
}

public class SDKManager {
    static public let shared = SDKManager()
    
    public weak var delegate: SDKManagerDelegate?
    
    private var sdkClasses: [SDKProtocol.Type] = [SystemSDK.self]
    
    private var sdks: [SDKProtocol] = []
    
    public var defaultThumbImage: UIImage?
    
    private init(){
        
    }
    
    public func register(sdkClass: SDKProtocol.Type, install: Bool = false) {
        guard !sdkClasses.contains(where: { $0.type == sdkClass.type }) else {
            return
        }
        
        sdkClasses.append(sdkClass)
        
        if install {
            let sdk = sdkClass.init()
            _ = sdk.install()
            sdks.append(sdk)
        }
    }
    
    public func shareClasses(shareTypes: [String]) -> [ShareProtocol.Type] {
        return shareTypes.compactMap { shareType in
            for sdkClass in sdkClasses {
                let shareClass = sdkClass.shareClasses?
                    .first(where: { $0.type == shareType })
                
                if shareClass != nil {
                    return shareClass
                }
            }
            
            return nil
        }
    }
    
    public func sdk(type: String) -> SDKProtocol? {
        var sdk = sdks.first { $0.type == type }
        
        if sdk != nil {
            return sdk
        }
        
        sdk = sdkClasses.first{ $0.type == type }?.init()
        
        _ = sdk?.install()
        
        if let sdk = sdk {
            sdks.append(sdk)
        }
        
        return sdk
    }
    
    public func shareInstance(type: String) -> ShareProtocol? {
        guard let sdkClass = sdkClasses.first(where: { $0.shareClasses?.contains(where: { $0.type == type }) == true }) else {
            return nil
        }
        
        guard let sdk = sdk(type: sdkClass.type) else {
            return nil
        }
        
        return sdk.shareClasses?.first{ $0.type == type }?.init()
    }
    
    public func loginInstance(type: String) -> LoginProtocol? {
        guard let sdkClass = sdkClasses.first(where: { $0.loginClass?.type == type }) else {
            return nil
        }
        
        guard let sdk = sdk(type: sdkClass.type) else {
            return nil
        }
        
        return sdk.loginClass?.init(sdk: sdk)
    }
    
    public func handLinkURL(_ url: URL) -> Bool {
        var result: Bool = false
        
        for sdk in sdks {
            if sdk.handLinkURL(url) {
                result = true
                break
            }
        }
        
        return result
    }
    
    public func continueUserActivity(_ userActivity: NSUserActivity) -> Bool {
        var result: Bool = false
        
        for sdk in sdks {
            if sdk.continueUserActivity(userActivity) {
                result = true
                break
            }
        }
        
        return result
    }
    
    public func createShareObject(values: [String: Any]) -> ShareObjectProtocol? {
        guard let type = values["type"] as? String else {
            return nil
        }
        
        switch ShareObjectType.allTypes[type] {
        case ShareObjectType.url:
            guard let url = values["url"] as? String else {
                return nil
            }
            
            return ShareUrlObject(title: values["title"] as? String,
                                  description: values["description"] as? String,
                                  thumbImage: nil,
                                  url: url)
        case ShareObjectType.image:
            guard let imageData = values["imageData"] as? String else {
                return nil
            }
            
            if let data = Data(base64Encoded: imageData), let image = UIImage(data: data) {
                return ShareImageObject(image: image)
            }
            return nil
        default:
            return nil
        }
    }
    
    public func share(shareObject: [String: Any], completion: ShareProtocol.Completion?) {
        delegate?.share(sdkManager: self, shareObject: shareObject, completion: completion)
    }
    
    public func share(shareObject: ShareObjectProtocol, completion: ShareProtocol.Completion?) {
        share(shareObject: shareObject.toJson(), completion: completion)
    }
    
    public func share(type: String,
                      shareObject: [String: Any],
                      completion: ShareProtocol.Completion?) {
        guard let value = SDKManager.shared.createShareObject(values: shareObject) else {
            completion?(false)
            return
        }
        
        share(type: type, shareObject: value, completion: completion)
    }
    
    public func share(type: String,
                      shareObject: ShareObjectProtocol,
                      completion: ShareProtocol.Completion?) {
        guard let share = shareInstance(type: type) else {
            completion?(false)
            return
        }
        
        share.share(shareObject: shareObject, completion: completion)
    }
}
